#include "app_device.h"

static app_buffer_t *up_buffer;
static app_buffer_t *down_buffer;

static uint8_t device_list[10];
static int device_nums = 0;

static pthread_t device_check_thread;

/**
 * @brief 设备模块初始化
 * 1 缓冲区 *2  上 下
 * 2 modbus初始化
 * 3 pool 初始化
 * 4 mqtt 初始化
 *
 */
int app_device_init(char *dev_file_name)
{
    //      * 1 缓冲区 *2  上 下
    up_buffer = app_buffer_init(1024);
    down_buffer = app_buffer_init(1024);
    if (up_buffer == NULL || down_buffer == NULL)
    {
        log_error("app_device_init:app_buffer_init error");
        return -1;
    }
    log_info("app_device_init:app_buffer_init ok");
    //  * 2 modbus初始化
    int ret = app_modbus_init(dev_file_name);
    if (ret == -1)
    {
        app_buffer_destroy(up_buffer);
        app_buffer_destroy(down_buffer);
        log_error("app_device_init:app_modbus_init error");
        return -1;
    }
    log_info("app_device_init:app_modbus_init ok");
    //  * 3 pool 初始化
    ret = app_pool_init();
    if (ret == -1)
    {
        log_error("app_device_init:app_pool_init error");
        app_buffer_destroy(up_buffer);
        app_buffer_destroy(down_buffer);
        app_modbus_destroy();
        return -1;
    }
    log_info("app_device_init:app_pool_init ok");
    //  * 4 mqtt 初始化
    ret = app_mqtt_init();
    if (ret == -1)
    {
        log_error("app_device_init:app_mqtt_init error");
        app_buffer_destroy(up_buffer);
        app_buffer_destroy(down_buffer);
        app_modbus_destroy();
        app_pool_destroy();
        return -1;
    }
    return 0;
}

/**
 * @brief 把json转换为字节数组
 */
//{"device_id":1,"motor_set_nums":800,"motor_status","on"} ==>  
// 01 03 20 01
static  int message_jsonToChars(  char *json, char *buffer, int buffer_len)
{
     if(buffer_len<4)
     {
        log_error("buffer is too small ");
     }
     cJSON *root = cJSON_Parse(json);
     if(root==NULL)
     {
        perror("json is invalid ");
        return -1;
     }
     

     cJSON *device_id_cjson=  cJSON_GetObjectItem(root, "device_id");
     cJSON *motor_set_nums_cjson=  cJSON_GetObjectItem(root, "motor_set_nums");
     cJSON *motor_status_cjson=  cJSON_GetObjectItem(root, "motor_status");

     uint8_t device_id=  device_id_cjson->valueint ;
     uint16_t  motor_set_nums=   motor_set_nums_cjson->valueint ;
     char  *motor_status_chr=   motor_status_cjson->valuestring ;


     buffer[0]=device_id;
     memcpy(buffer+1, &motor_set_nums, 2);
     buffer[3]= strcmp(motor_status_chr,"on") ==0 ?1:0;

     
     app_common_printHex("app_message_jsonToChars :", buffer, 4);
     cJSON_Delete(root);
     return 4;
}


/**
 * @brief 把字节数组转换为json
 *   // 01 00 10 01
 *  => {"device_id":1,"motor_speed":16,"motor_status":"on"}
 */
char   *message_charsToJson(  char *data, int data_len   )
{
      // 先把data提取成值
      uint8_t device_id=data[0];
      uint16_t motor_speed= 0;
      memcpy(&motor_speed, data+1, 2);
      uint8_t  motor_status=data[3];
      
 
      // cjson结构体 生成json字符串
      cJSON *root = cJSON_CreateObject();
      cJSON_AddNumberToObject(root, "device_id", device_id);
      cJSON_AddNumberToObject(root, "motor_speed", motor_speed);
      cJSON_AddStringToObject(root, "motor_status", motor_status?"on":"off");

      char *jsonstr=   cJSON_PrintUnformatted(root );
       cJSON_Delete(root);
      return jsonstr;
      
}

/**
 * @brief 把deviceId 写入待监控设备列表
 */
void add_device_id(int device_id)
{
    device_list[device_nums]=device_id;
    device_nums++;
}

/**
 * @brief 从设备列表中删除设备id
 */
void remove_device_id(int device_id)
{
    int i;
    for(i=0;i<device_nums;i++)
    {   
        if(device_list[i]==device_id)
        {
            // 用后面的元素 覆盖掉当前元素
            memmove(&device_list[i],&device_list[i+1],device_nums-i-1);
            device_nums--;
            return;
        }
    }
}


/**
 * @brief 下行通路 后半程 由线程池完成 
 * 1  从下行缓冲提取数据
 * 2  把数据写发送到modbus 2条   速度+ 开关
 * 3  把设备id写入 设备监控列表
 */
static void *down2_writeModbus(void *arg)
{
// * 1  从下行缓冲提取数据
    char data_buff[10];
      app_buffer_read(down_buffer,data_buff,10);
// * 2  把数据写发送到modbus 2条   速度+ 开关
    uint8_t device_id= data_buff[0];
    uint16_t motor_set_nums=0;
    memcpy(&motor_set_nums,data_buff+1,2);
    uint8_t motor_status =data_buff[3];
    app_modbus_writeHoldingRegister(device_id,2,1,&motor_set_nums); //速度

    app_modbus_writeCoil(device_id,2,1,&motor_status);   //开关
// * 3  把设备id写入 设备监控列表
    add_device_id(device_id);

    return NULL;
}

/**
 * @brief 接收mqtt消息的回调
 * //1  把接收的json转换
//  //2 写入下行缓冲
   //3 提交后续任务给线程池
 */
  int down1_mqtt_messageCallback (char *message_payload)
  {
       //1  把接收的json转换
       char data_buff[10];
      int data_len=  message_jsonToChars(message_payload,data_buff,10);
      if(data_len<=0)
      {
        return -1;
      }
       //2 写入下行缓冲
      int ret= app_buffer_write(down_buffer, data_buff,data_len);
      if(ret<0)
      {
        return -1;
      }
        //3 提交后续任务给线程池
        app_pool_submitTask(down2_writeModbus,NULL);

        return 0;
  }

  /**
   * @brief 上行数据处理 由线程池完成  上行通路 下半部分 
   * 1 从缓冲区提取数据
   * 2 转换为json
   * 3 发送mqtt 
   * 4 如果电机状态为关 从设备列表中删除该设备
   */
static void *up2_sendMqttMsg(void *arg)
{
//    * 1 从缓冲区提取数据
    char data_buff[4];
    app_buffer_read(up_buffer,  data_buff,4);

//    * 2 转换为json
    char *json= message_charsToJson(data_buff,4);

//    * 3 发送mqtt 
    app_mqtt_sendMessage(json);
    cJSON_free(json);
//    * 4 如果电机状态为关 从设备列表中删除该设备
     uint8_t motor_status= data_buff[3];
     uint8_t device_id= data_buff[0];
     if(motor_status==0)
     {
        remove_device_id(  device_id);
     }
     return NULL;
}

/**
 * @brief  扫描设备列表 并 查询设备的数值   上行通信 上半部分 
 * 1 扫描设备列表
 * 2   如果有需要检查的设备   对该设备发送 modbus的读指令
 *      3  数值组合后放入缓冲区
 *     4 向线程池提交后续的任务
 */
static void *up1_checkDeviceAndReadModbus(void *arg)
{ 
    while(1)
    { 
        for(int i = 0; i < device_nums; i++)
        {
            //   对该设备发送 modbus的读指令
            uint8_t device_id= device_list[i];
            uint8_t motor_cur_status=0;
            uint16_t motor_speed=0;
            app_modbus_readCoil(device_id, 2, 1, &motor_cur_status);
            app_modbus_readInputRegister(device_id, 2, 1, &motor_speed);
            //  数值组合后放入缓冲区
            uint8_t data_buff[4];
            data_buff[0]=device_id;
            memcpy(data_buff+1, &motor_speed, 2);
            data_buff[3]=motor_cur_status;
            app_buffer_write(up_buffer,(char *)data_buff,4);

            //向线程池提交后续的任务
            app_pool_submitTask(up2_sendMqttMsg,NULL);

        }
        sleep(1);

    }
    return NULL;
}


/**
 * @brief 设备模块启动
 * 1  向mqtt 注册回调  下行通路 起点
 * 2  启动线程 扫描监控设备列表
 */
int app_device_start(void)
{
//  * 1  向mqtt 注册回调  下行通路 起点
    app_mqtt_registerMessageCallback(down1_mqtt_messageCallback);
//  * 2  启动线程 扫描监控设备列表  上行通路 起点
    pthread_create(&device_check_thread,NULL,up1_checkDeviceAndReadModbus,NULL);


   log_info("app_device_start..............");

   return 0;
}










/**
 * @brief 设备模块销毁
 */
void app_device_destroy(void)
{
       log_info("app_device_destroy..............");
        pthread_cancel(device_check_thread);
        pthread_join(device_check_thread,NULL);


        app_buffer_destroy(up_buffer);
        app_buffer_destroy(down_buffer);
        app_modbus_destroy();
        app_pool_destroy();
        app_mqtt_destroy();
}